﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ConvertUtility.cs" company="">
//   
// </copyright>
// <summary>
//   The convert utility.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Libium.Core
{
    using System;
    using System.Runtime.InteropServices;

    /// <summary>
    ///   The convert utility.
    /// </summary>
    public static class ConvertUtility
    {
        #region Public Methods and Operators

        /// <summary>
        /// The bytes to struct.
        /// </summary>
        /// <param name="bytes">
        /// The bytes. 
        /// </param>
        /// <typeparam name="T">
        /// </typeparam>
        /// <returns>
        /// The <see cref="T"/> . 
        /// </returns>
        public static T BytesToStruct<T>(byte[] bytes) where T : struct
        {
            var ptr = IntPtr.Zero;
            try
            {
                var size = Marshal.SizeOf(typeof(T));
                ptr = Marshal.AllocHGlobal(size);
                Marshal.Copy(bytes, 0, ptr, size);
                var obj = Marshal.PtrToStructure(ptr, typeof(T));
                return (T)obj;
            }
            finally
            {
                if (ptr != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(ptr);
                }
            }
        }

        /// <summary>
        /// The struct to bytes.
        /// </summary>
        /// <param name="obj">
        /// The obj. 
        /// </param>
        /// <typeparam name="T">
        /// </typeparam>
        /// <returns>
        /// The <see cref="byte[]"/> . 
        /// </returns>
        public static byte[] StructToBytes<T>(T obj) where T : struct
        {
            var ptr = IntPtr.Zero;
            try
            {
                var size = Marshal.SizeOf(typeof(T));
                ptr = Marshal.AllocHGlobal(size);
                Marshal.StructureToPtr(obj, ptr, true);
                var bytes = new byte[size];
                Marshal.Copy(ptr, bytes, 0, size);
                return bytes;
            }
            finally
            {
                if (ptr != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(ptr);
                }
            }
        }

        #endregion
    }
}